package com.example.onlineanswer.service.impl;

import com.example.onlineanswer.model.dto.RankingDTO;
import com.example.onlineanswer.service.ContestRankingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 竞赛排名服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ContestRankingServiceImpl implements ContestRankingService {

    private final RedisTemplate<String, Object> redisTemplate;
    
    // Redis key前缀
    private static final String RANKING_KEY_PREFIX = "contest:ranking:";
    private static final String USER_INFO_KEY_PREFIX = "contest:user:";
    
    /**
     * 构建排名Redis Key
     */
    private String getRankingKey(Long contestId) {
        return RANKING_KEY_PREFIX + contestId;
    }
    
    /**
     * 构建用户信息Redis Key
     */
    private String getUserInfoKey(Long contestId) {
        return USER_INFO_KEY_PREFIX + contestId;
    }

    @Override
    public boolean updateUserRanking(Long contestId, Long userId, int score) {
        try {
            String rankingKey = getRankingKey(contestId);
            // 使用ZSet来存储排名，分数作为key，用户ID作为value
            // 分数越高，排名越靠前
            redisTemplate.opsForZSet().add(rankingKey, userId.toString(), score);
            return true;
        } catch (Exception e) {
            log.error("更新用户排名异常: {}", e.getMessage());
            return false;
        }
    }

    @Override
    public List<RankingDTO> getRankingList(Long contestId, int start, int end) {
        try {
            String rankingKey = getRankingKey(contestId);
            String userInfoKey = getUserInfoKey(contestId);
            
            // 获取前N名的用户ID和分数（按分数从高到低排序）
            Set<ZSetOperations.TypedTuple<Object>> rankSet = 
                    redisTemplate.opsForZSet().reverseRangeWithScores(rankingKey, start, end);
            
            if (rankSet == null || rankSet.isEmpty()) {
                return new ArrayList<>();
            }
            
            // 收集所有用户ID
            List<String> userIds = rankSet.stream()
                    .map(item -> (String) item.getValue())
                    .collect(Collectors.toList());
            
            // 获取所有用户的信息
            List<Object> userInfoList = redisTemplate.opsForHash().multiGet(
                    userInfoKey, userIds.stream().map(id -> (Object) id).collect(Collectors.toList()));
            
            // 将用户信息和排名合并
            List<RankingDTO> result = new ArrayList<>();
            int rank = start + 1;
            
            for (ZSetOperations.TypedTuple<Object> tuple : rankSet) {
                RankingDTO dto = new RankingDTO();
                String userId = (String) tuple.getValue();
                dto.setUserId(Long.valueOf(userId));
                dto.setScore(tuple.getScore().intValue());
                
                // 查找用户信息
                int userIndex = userIds.indexOf(userId);
                if (userIndex >= 0 && userIndex < userInfoList.size()) {
                    Map<String, String> userInfo = (Map<String, String>) userInfoList.get(userIndex);
                    if (userInfo != null) {
                        dto.setNickname(userInfo.get("nickname"));
                        dto.setUserAvatar(userInfo.get("userAvatar"));
                    }
                }
                
                result.add(dto);
                rank++;
            }
            
            return result;
        } catch (Exception e) {
            log.error("获取竞赛排名列表异常: {}", e.getMessage());
            return new ArrayList<>();
        }
    }

    @Override
    public RankingDTO getUserRanking(Long contestId, Long userId) {
        try {
            String rankingKey = getRankingKey(contestId);
            String userInfoKey = getUserInfoKey(contestId);
            
            // 获取用户分数
            Double score = redisTemplate.opsForZSet().score(rankingKey, userId.toString());
            if (score == null) {
                return null;
            }
            
            // 获取用户排名
            Long rank = redisTemplate.opsForZSet().reverseRank(rankingKey, userId.toString());
            if (rank == null) {
                rank = 0L;
            }
            
            // 获取用户信息
            Map<Object, Object> userInfo = redisTemplate.opsForHash().entries(userInfoKey);
            
            RankingDTO dto = new RankingDTO();
            dto.setUserId(userId);
            dto.setScore(score.intValue());
            
            if (userInfo.containsKey(userId.toString())) {
                Map<String, String> info = (Map<String, String>) userInfo.get(userId.toString());
                dto.setNickname(info.get("nickname"));
                dto.setUserAvatar(info.get("userAvatar"));
            }
            
            return dto;
        } catch (Exception e) {
            log.error("获取用户排名信息异常: {}", e.getMessage());
            return null;
        }
    }

    @Override
    public void setUserRankingInfo(Long contestId, Long userId, String nickname, String userAvatar) {
        try {
            String userInfoKey = getUserInfoKey(contestId);
            
            // 存储用户信息到Hash
            Map<String, String> userInfo = new HashMap<>();
            userInfo.put("nickname", nickname);
            userInfo.put("userAvatar", userAvatar);
            
            redisTemplate.opsForHash().put(
                    userInfoKey, 
                    userId.toString(), 
                    userInfo
            );
        } catch (Exception e) {
            log.error("设置用户排名详细信息异常: {}", e.getMessage());
        }
    }

    @Override
    public Long getUserRank(Long contestId, Long userId) {
        try {
            String rankingKey = getRankingKey(contestId);
            
            // 获取用户排名（0为第一名）
            Long rank = redisTemplate.opsForZSet().reverseRank(rankingKey, userId.toString());
            
            // 返回从1开始的排名
            return rank != null ? rank + 1 : null;
        } catch (Exception e) {
            log.error("获取用户排名位置异常: {}", e.getMessage());
            return null;
        }
    }

    @Override
    public Long getContestParticipantsCount(Long contestId) {
        try {
            String rankingKey = getRankingKey(contestId);
            
            // 获取参与人数
            return redisTemplate.opsForZSet().zCard(rankingKey);
        } catch (Exception e) {
            log.error("获取竞赛参与人数异常: {}", e.getMessage());
            return 0L;
        }
    }

    @Override
    public boolean clearContestRanking(Long contestId) {
        try {
            String rankingKey = getRankingKey(contestId);
            String userInfoKey = getUserInfoKey(contestId);
            
            // 删除排名和用户信息
            redisTemplate.delete(rankingKey);
            redisTemplate.delete(userInfoKey);
            
            return true;
        } catch (Exception e) {
            log.error("清除竞赛排名异常: {}", e.getMessage());
            return false;
        }
    }
} 